package com.bm.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bm.Do.Common.InfoDo;
import com.bm.Result.CodeEnum;
import com.bm.Result.Result;
import com.bm.Vo.Login.LoginInfoVo;
import com.bm.Vo.Login.ValidateCodeVo;
import com.bm.Vo.CompanyUser.ejyyCompanyUserVo;
import com.bm.constant.Constants;
import com.bm.exception.BmException;
import com.bm.mapper.*;
import com.bm.model.*;
import com.bm.query.Login.AccountLoginQuery;
import com.bm.query.init.InitQuery;
import com.bm.service.EjyyPropertyCompanyUserAccessCommunityService;
import com.bm.service.EjyyPropertyCompanyUserService;
import com.bm.util.AuthContextUtil;
import com.bm.util.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 *
 */
@Service
public class EjyyPropertyCompanyUserServiceImpl extends ServiceImpl<EjyyPropertyCompanyUserMapper, EjyyPropertyCompanyUser>
        implements EjyyPropertyCompanyUserService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private EjyyUserCarMapper ejyyUserCarMapper;

    @Autowired
    private EjyyPropertyCompanyUserMapper ejyyPropertyCompanyUserMapper;

    @Autowired
    private EjyyCommunitySettingMapper ejyyCommunitySettingMapper;

    @Autowired
    private EjyyCommunityInfoMapper communityInfoMapper;
    @Autowired
    private EjyyPropertyCompanyUserAccessCommunityMapper propertyCompanyUserAccessCommunityMapper;

    @Autowired
    private EjyyPropertyCompanyAuthMapper propertyCompanyAuthMapper;
    @Override
    public Result login(AccountLoginQuery accountLoginQuery) {
        //先从redis里取出验证码
        String captchaCode = accountLoginQuery.getCaptcha();
        if (StringUtils.isEmpty(captchaCode)) {
            //如果没有传验证码过来
            return Result.FAIL(CodeEnum.VALIDATE_CODE_IS_EMPTY);
        }
        //从redis中获取验证码
        String code = stringRedisTemplate.opsForValue().get(Constants.VALIDATE_CODE_REDIS_KEY + captchaCode);
        if(StringUtils.isEmpty(captchaCode)){
            return Result.FAIL(CodeEnum.REDIS_VALIDATE_CODE_EMPTY);
        }
        //如果验证码不一致
        if(!captchaCode.equals(code)){
            return Result.FAIL(CodeEnum.VALIDATE_CODE_UNLIKE);
        }
        //验证码一致
        String account = accountLoginQuery.getAccount();

        String password = DigestUtils.md5DigestAsHex(accountLoginQuery.getPassword().getBytes());

        LambdaQueryWrapper<EjyyPropertyCompanyUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(EjyyPropertyCompanyUser::getAccount,account);
        lqw.eq(EjyyPropertyCompanyUser::getPassword,password);

        EjyyPropertyCompanyUser ejyyCompanyUser = ejyyPropertyCompanyUserMapper.selectOne(lqw);

        if(ObjectUtils.isEmpty(ejyyCompanyUser)){
            return Result.FAIL(CodeEnum.LOGIN_PASSWORD_ERROR);
        }
        //生成token
        String token = UUID.randomUUID().toString();
        //将token放入redis 有效期30分钟
        stringRedisTemplate.opsForValue().set(Constants.VALIDATE_CODE_REDIS_KEY+token,token,30,TimeUnit.MINUTES);

        ejyyCompanyUserVo ejyyCompanyUserVo = new ejyyCompanyUserVo();
        ejyyCompanyUserVo.setToken(token);
        BeanUtils.copyProperties(ejyyCompanyUser,ejyyCompanyUserVo);

        //将个人信息存入线程中
        InfoDo userInfo = new InfoDo();
        userInfo.setId(ejyyCompanyUserVo.getId());
        userInfo.setRealName(ejyyCompanyUserVo.getRealName());

        AuthContextUtil.set(userInfo);

        return Result.OK(ejyyCompanyUserVo);
    }

    /**
     * 生成验证码
     *
     * @return
     */
    @Override
    public ValidateCodeVo createValidateCode() {
        //借助htuool工具
        CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(150, 48, 4, 20);
        String code = captcha.getCode();
        String imageBase64 = captcha.getImageBase64(); //返回图片的编码格式base64编码
        //生成uuid
//        String key = UUID.randomUUID().toString().replaceAll("-", "");
        String key = code;
        //存入redis里 并且设置5分钟过期时间
        stringRedisTemplate.opsForValue().set(Constants.VALIDATE_CODE_REDIS_KEY + key, code, 5, TimeUnit.MINUTES);
        //封装返回对象  ValidateCodeVo
        ValidateCodeVo validateCodeVo = new ValidateCodeVo();
        validateCodeVo.setCodeKey(key);
        validateCodeVo.setCodeValue("data:image/png;base64," + imageBase64);
        return validateCodeVo;
    }

    /**
     * 用户登录初始化数据
     *
     * @return
     */
    @Override
    public LoginInfoVo getUserInfo() {
        //创建vo对象
        LoginInfoVo loginInfoVo = new LoginInfoVo();
        //封装vo对象
        loginInfoVo.setUserRoomCount(ejyyPropertyCompanyUserMapper.selectCount(new LambdaQueryWrapper<>()));
        loginInfoVo.setUserCarCount(ejyyUserCarMapper.selectCount(new LambdaQueryWrapper<>()));
        loginInfoVo.setHousingCount(RandomUtil.randomInt(20,40));
        List<Integer> serveCount = new ArrayList<>();
        List<Integer> visitorCount = new ArrayList<>();
        List<Integer> informCount = new ArrayList<>();
        for (int i = 0; i < 7; i++) {
            serveCount.add(RandomUtil.randomInt(20,50));
            visitorCount.add(RandomUtil.randomInt(20,55));
            informCount.add(RandomUtil.randomInt(10,40));
        }
        loginInfoVo.setServeCount(serveCount);
        loginInfoVo.setVisitorCount(visitorCount);
        loginInfoVo.setInformCount(informCount);
        return loginInfoVo;
    }

    /**
     * 退出登录
     */
    @Override
    public boolean logout(HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("Authorization");
        //删除线程中的个人信息
        AuthContextUtil.remove();
        return stringRedisTemplate.delete(Constants.REDIS_TOKEN_KEY + token);

    }

    /**
     * 修改密码
     *
     * @return
     */
    @Transactional
    @Override
    public boolean reset(EjyyPropertyCompanyUser propertyCompanyUser) {
        if(ObjectUtils.isEmpty(propertyCompanyUser)){
            //如果密码为空的话
            throw new BmException(CodeEnum.SYSTEM_PARAMETER_IS_EMPTY);
        }
        if(!StringUtils.hasText(propertyCompanyUser.getPassword())){
            //如果密码为空的话
            throw new BmException(CodeEnum.SYSTEM_PARAMETER_IS_EMPTY);
        }
        String newPassword = DigestUtils.md5DigestAsHex(propertyCompanyUser.getPassword().getBytes());
        propertyCompanyUser.setPassword(newPassword);

        boolean flag = ejyyPropertyCompanyUserMapper.updatePassword(propertyCompanyUser);

        return flag;
    }


    /**
     * 初始化数据
     * @param initQuery
     * @return
     */
    @Override
    public Boolean initRun(InitQuery initQuery) {
        LambdaQueryWrapper<EjyyPropertyCompanyUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(EjyyPropertyCompanyUser::getAdmin,true);
        Integer total = ejyyPropertyCompanyUserMapper.selectCount(lqw);
        if(total > 0){
            return null;
        }
        EjyyPropertyCompanyUser ejyyPropertyCompanyUser = new EjyyPropertyCompanyUser();

        BeanUtils.copyProperties(initQuery,ejyyPropertyCompanyUser);
        //封装数据
        ejyyPropertyCompanyUser.setPassword(DigestUtils.md5DigestAsHex(initQuery.getPassword().getBytes()));
        ejyyPropertyCompanyUser.setAdmin(true);
        ejyyPropertyCompanyUser.setCreatedBy(DateUtils.dateConversion());
        ejyyPropertyCompanyUser.setLeaveOffice(false);
        String idcard = initQuery.getIdcard();
        if(idcard == null || idcard == ""){
            ejyyPropertyCompanyUser.setGender(0);
        }else{
            char c;
            try {
                 c = idcard.charAt(16);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            ejyyPropertyCompanyUser.setGender(c % 2 == 0 ? 2 : 1);
        }
        //新增用户信息
        int insert = ejyyPropertyCompanyUserMapper.insert(ejyyPropertyCompanyUser);
        //创建条件
        LambdaQueryWrapper<EjyyPropertyCompanyUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.orderByDesc(EjyyPropertyCompanyUser::getId);
        List<EjyyPropertyCompanyUser> userList = ejyyPropertyCompanyUserMapper.selectList(lambdaQueryWrapper);


        EjyyCommunityInfo ejyyCommunityInfo = new EjyyCommunityInfo();
        BeanUtils.copyProperties(initQuery,ejyyCommunityInfo);
        ejyyCommunityInfo.setPhone(initQuery.getServicePhone());
        Integer userId = userList.get(0).getId();
        ejyyCommunityInfo.setCreatedBy(Long.parseLong(userList.get(0).getId()+""));
        //新增社区信息
        int communityCount = communityInfoMapper.insert(ejyyCommunityInfo);
        //查询社区id
        LambdaQueryWrapper<EjyyCommunityInfo> communitLqw = new LambdaQueryWrapper<>();
        communitLqw.orderByDesc(EjyyCommunityInfo::getId);
        //按倒序查询所有社区id
        List<EjyyCommunityInfo> ejyyCommunityInfos = communityInfoMapper.selectList(communitLqw);
        //获取社区id
        Long communityId = ejyyCommunityInfos.get(0).getId();

        //创建社区设置对象
        EjyyCommunitySetting ejyyCommunitySetting = new EjyyCommunitySetting();
        BeanUtils.copyProperties(initQuery,ejyyCommunitySetting);
        //封装社区id
        ejyyCommunitySetting.setCommunityId(communityId);
        //新增社区设置信息
        ejyyCommunitySettingMapper.insert(ejyyCommunitySetting);

        EjyyPropertyCompanyUserAccessCommunity userAccessCommunity = new EjyyPropertyCompanyUserAccessCommunity();
        userAccessCommunity.setPropertyCompanyUserId(Long.valueOf(userId));
        userAccessCommunity.setCommunityId(communityId);
        propertyCompanyUserAccessCommunityMapper.insert(userAccessCommunity);

        EjyyPropertyCompanyAuth propertyCompanyAuth = new EjyyPropertyCompanyAuth();
        propertyCompanyAuth.setPropertyCompanyUserId(Long.valueOf(userId));
        propertyCompanyAuth.setToken(null);
        propertyCompanyAuthMapper.insert(propertyCompanyAuth);

        //在配置中设置已经初始化
//        config.inited = true;

        return true;
    }
}
